package presenter

import com.github.thomasnield.rxkotlinfx.observeOnFx
import entity.PbcEbookEntity
import entity.SysProperties
import io.reactivex.Observable
import io.reactivex.schedulers.Schedulers
import model.FileControlModel
import util.MyDbHelper
import model.PbcEbooksModel
import model.SysPropertiesModel
import tornadofx.*
import util.MyEncodeUtil
import view.LoginView
import view.MainWindow
import java.io.File

class MainPresenter : Controller() {
    val sysPropertiesModel = SysPropertiesModel(this)
    val pbcEbooksModel = PbcEbooksModel()
    val fileControlModel = FileControlModel(this)

    val mainWindow: MainWindow by inject()
    val loginView: LoginView by inject()


    fun requestDatas() {
        Observable.just(MyDbHelper.instance.onCreateTable())
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .map { sysPropertiesModel.getSysPropertiesFromFile() }
                .observeOnFx()
                .doOnNext { mainWindow.refreshViewFromProPerties(it) }
                .observeOn(Schedulers.io())
                .map { pbcEbooksModel.getAllEbooks() }
                .observeOnFx()
                .subscribe {
                    mainWindow.loadTreeView(it)
                }
    }

    fun setSysProperties(sysProperties: SysProperties) {
        sysPropertiesModel.saveProperties(sysProperties)
    }



    fun addNewBooks(importFiles: List<File>, parentPath: String) {
        Observable.just(0)
                .observeOn(Schedulers.io())
                .map { pbcEbooksModel.changeWordToHtml(importFiles, parentPath) }
                .map { pbcEbooksModel.addNewBooksToDb(it, parentPath) }
                .observeOnFx()
                .subscribe {
                    mainWindow.addNewBooksToUI(it)
                }
    }


    fun initDB() {
        MyDbHelper.instance.onCreateTable()
        MyDbHelper.instance.onClose()
    }

    fun addNewFold(foldName: String, parentPath: String) {
        tornadofx.runAsync {
            val newFoldEntity = PbcEbookEntity(0, foldName, "$parentPath/$foldName", true, "")
            val resultCode = pbcEbooksModel.addNewFoldIntoDb(newFoldEntity)
            newFoldEntity.copy(id = resultCode)
        } ui { response -> mainWindow.addNewFoldToUI(response)}
    }


    fun updateBookById(newFile: File, oldBook: PbcEbookEntity, isDir: Boolean) {
        Observable.just(0)
                .observeOn(Schedulers.io())
                .map { pbcEbooksModel.changeWordToHtml(listOf(newFile), pbcEbooksModel.getParentPath(oldBook.path, isDir)) }
                .map {
                    pbcEbooksModel.removeOldFiles(oldBook.content)
                    it
                }
                .filter { it.isNotEmpty() }
                .map { pbcEbooksModel.updateBookContentIntoDb(it[0], oldBook) }
                .observeOnFx()
                .subscribe {
                    mainWindow.updateBookChangeToUI(oldBook, it)
                }
    }

    fun exportDatas(desPath: String) {
        fileControlModel.exportDatas(desPath)
    }

    fun updateBookName(newName: String, ebook: PbcEbookEntity) {
        runAsync {
            pbcEbooksModel.updateBookNameIntoDb(newName, ebook)
        } ui { result ->
            if (result > 0)
                mainWindow.updateBookChangeToUI(ebook, listOf(ebook.copy(name = newName)))
        }
    }



    fun removeEbooks(removeBooks: PbcEbookEntity) {
        // Finished
        Observable.just(fileControlModel.removeEbooks(removeBooks))
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .map { pbcEbooksModel.removeEbooks(removeBooks) }
                .map { pbcEbooksModel.getAllEbooks() }
                .observeOnFx()
                .subscribe { mainWindow.loadTreeView(it) }
    }



    fun importDatas(importFile: File) {
        fileControlModel.importDatas(importFile)
    }

    fun searchKeyWordsInName(searchText: String) {
        Observable.just(0)
                .observeOn(Schedulers.io())
                .map {
                    MyDbHelper.instance.selectEbooksByKeyWordsInName(searchText)
                }
                .observeOnFx()
                .subscribe {
                    mainWindow.addSearchResultToList(it, searchText, true)
                }
    }



    fun searchKeyWordsInContent(keyWords: String) {
        Observable.just(0)
                .observeOn(Schedulers.io())
                .map {
                    MyDbHelper.instance.selectAllEbooks()
                }
                .observeOnFx()
                .filter { !it.isEmpty() }
                .map {
                    val ebooks = mutableListOf<PbcEbookEntity>()
                    it.forEach {
                        if (File(it.content).exists() && File(it.content).readText().contains(keyWords, true)) {
                            ebooks.add(it)
                        }
                    }
                    ebooks
                }
                .subscribe {
                    mainWindow.addSearchResultToList(it, keyWords, false)
                }
    }

    fun requestLoginToApp(loginUser: String, loginPwd: String) {
        Observable.just(sysPropertiesModel.getSysPropertiesFromFile())
                .subscribeOn(Schedulers.io())
                .observeOnFx()
                .subscribe {
                    if ((it.loginUser == loginUser)&&(it.loginPwd == MyEncodeUtil.encode(loginPwd))) {
                        loginView.loginSuccess()
                    } else {
                        loginView.loginFailed()
                    }
                }
    }



    fun exchangeTwoEbooks(selectedItem: PbcEbookEntity, anotherItem: PbcEbookEntity) {
        runAsync {
            MyDbHelper.instance.exchangeTowEbooks(selectedItem, anotherItem)
            pbcEbooksModel.getAllEbooks()
        } ui {
            mainWindow.loadTreeView(it)
        }
    }
}